package de.hs_mannheim.visualscheduler.gui;

import java.util.ArrayList;
import javax.swing.table.AbstractTableModel;
import de.hs_mannheim.visualscheduler.scheduling.ProcessDefinition;

/**
 * The Class ProcessTableModel combines an ArrayList with a TableModel. This Object can be used to store ProccessDefinitions and
 * provides a Tabular-View of the stored items.
 * 
 * @see javax.swing.table.TableModel
 * @see java.util.List
 */
public final class ProcessTableModel extends AbstractTableModel {
	private static final long					serialVersionUID	= 7384368442436830761L;
	private final ArrayList<ProcessDefinition>	processes			= new ArrayList<ProcessDefinition>();

	/**
	 * Adds a ProcessDefinition to ProcessTableModel.
	 * 
	 * @param processDefinition
	 *            to add
	 * @return true, if successful
	 */
	public boolean add(final ProcessDefinition processDefinition) {
		final boolean ret = processes.add(processDefinition);
		fireTableDataChanged();
		return ret;
	}

	@Override
	public int getColumnCount() {
		return 4;
	}

	@Override
	public String getColumnName(final int column) {
		switch (column) {
			case 1:
				return "Priority";
			case 2:
				return "Runtime";
			case 3:
				return "Arrival";
			case 0:
			default:
				return "Name";
		}
	}

	/**
	 * Gets the processes.
	 * 
	 * @return the processes
	 */
	public ProcessDefinition[] getProcesses() {
		return processes.toArray(new ProcessDefinition[processes.size()]);
	}

	@Override
	public int getRowCount() {
		return processes.size();
	}

	@Override
	public Object getValueAt(final int arg0, final int arg1) {
		final ProcessDefinition p = processes.get(arg0);
		switch (arg1) {
			case 1:
				return p.getPriority();
			case 2:
				return p.getRuntime();
			case 3:
				return p.getArrival();
			case 0:
			default:
				return p.getName();
		}
	}
	
	@Override
	public boolean isCellEditable(int rowIndex, int columnIndex) {
		return true;
	}
	
	@Override
	public Class<?> getColumnClass(int columnIndex) {
		if(columnIndex == 0)
			return String.class;
		return Integer.class;
	}
	
	@Override
	public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
		ProcessDefinition editedDefinition = processes.get(rowIndex);
		switch (columnIndex) {
			case 1:
				editedDefinition.setPriority((Integer) aValue);
				break;
			case 2:
				editedDefinition.setRuntime((Integer) aValue);
				break;
			case 3:
				editedDefinition.setArrival((Integer) aValue);
				break;
			case 0:
			default:
				editedDefinition.setName("" + aValue);
		}
	}
	
	/**
	 * Removes the element at the specified index.
	 * 
	 * @param index
	 *            of the element to remove
	 * @return true, if successful
	 */
	public boolean remove(final int index) {
		final boolean ret = processes.remove(index) != null;
		fireTableDataChanged(); // Update TableModel
		return ret;
	}

	/**
	 * Removes the specified Object from the ProcessTableModel.
	 * 
	 * @param object to remove
	 *            
	 * @return true, if successful
	 */
	public boolean remove(final Object object) {
		final boolean ret = processes.remove(object);
		fireTableDataChanged(); // Update TableModel
		return ret;
	}

	/**
	 * Sets the processes from an Array.
	 * <b>Replaces all existing definitions</b>
	 * 
	 * @param processes
	 *            the new processes
	 */
	public void setProcesses(final ProcessDefinition[] processes) {
		this.processes.clear();
		for (final ProcessDefinition pd : processes) {
			this.processes.add(pd);
		}
		fireTableDataChanged(); // Update TableModel
	}

	/**
	 * Return all processDefinitions as an Array.
	 * 
	 * @return the array of processDefinitions currently contained in ProcessTableModel
	 */
	public ProcessDefinition[] toArray() {
		return processes.toArray(new ProcessDefinition[processes.size()]);
	}
}
